//////////////////////////////////////
// Fast Container Library           //
// MIT License - Copyright (c) 2012 //
//////////////////////////////////////

#pragma once

#include "forward.h"
#include "basic_string.h"
#include "fixed_allocator.h"


FC_NAMESPACE_BEGIN


template <class T, size_t N, class Allocator>
class fixed_string : public basic_string<T, Allocator>
{
public:
	typedef fixed_string<T, N, Allocator>				this_type;
	typedef basic_string<T, Allocator>					base_type;
	typedef typename base_type::allocator_type			allocator_type;
	typedef typename base_type::size_type				size_type;
	typedef typename base_type::value_type				value_type;
	typedef typename base_type::pointer					pointer;
	typedef typename base_type::iterator				iterator;
	typedef typename base_type::const_iterator			const_iterator;

	using base_type::m_allocator;
	using base_type::m_begin;
	using base_type::m_end;
	using base_type::m_capacity;
	using base_type::npos;

	fixed_string()
		: base_type(uninitialized_construct(), allocator_type())
		{
			init();
		}

	explicit fixed_string( T c )
		: base_type(uninitialized_construct(), allocator_type())
		{
			init();
			base_type::append( c );
		}

	fixed_string( const this_type& str )
		: base_type(uninitialized_construct(), allocator_type())
		{
			init();
			base_type::append( str.begin(), str.end() );
		}

	fixed_string( const basic_string_ref<T>& str )
		: base_type(uninitialized_construct(), allocator_type())
		{
			init();
			base_type::append( str.begin(), str.end() );
		}

	fixed_string( const basic_string_ref<T>& str, size_t pos, size_t n = npos )
		: base_type(uninitialized_construct(), allocator_type())
		{
			init();
			const_iterator last = (n == npos ? str.end() : str.begin() + pos + n);
			base_type::append( str.begin() + pos, last );
		}

	fixed_string( const T* s, size_t n )
		: base_type(uninitialized_construct(), allocator_type())
		{
			init();
			base_type::append( s, s + n );
		}

	fixed_string( const T* s )
		: base_type(uninitialized_construct(), allocator_type())
		{
			init();
			base_type::append( s );
		}

	fixed_string( size_t n, T c )
		: base_type(uninitialized_construct(), allocator_type())
		{
			init();
			base_type::append( n, c );
		}

	fixed_string( const_iterator first, const_iterator last )
		: base_type(uninitialized_construct(), allocator_type())
		{
			init();
			base_type::append( first, last );
		}

	fixed_string( size_t n, const char* format, ... )
		: base_type(uninitialized_construct(), allocator_type())
		{
			reset();
			va_list args;
			va_start(args, format);
			base_type::append_args( n, format, args );
			va_end(args);
		}

	//template <class U>
	//this_type& operator =( const basic_string<T, U>& str ) { return (this_type&)base_type::assign(str.m_begin, str.m_end); }
	this_type& operator =( const this_type& str ) { return (this_type&)base_type::assign(str.m_begin, str.m_end); }
	this_type& operator =( const basic_string_ref<T>& str ) { return (this_type&)base_type::assign(str.m_begin, str.m_end); }
	this_type& operator =( const T* s ) { return (this_type&)base_type::assign(s); }
	this_type& operator =( T c )		{ return (this_type&)base_type::assign(size_t(1), c); }

	this_type substr( size_type pos, size_type n ) const
	{
		return this_type( m_begin + pos, fc::min<T*>(m_begin + pos + n, m_end) );
	}

	this_type substr( const_iterator first, const_iterator last ) const
	{
		FC_ASSERT(iterator_is_valid(first) && iterator_is_valid(last) && first <= last);
		return this_type(first, last);
	}

	bool has_overflowed() const
	{
		return (m_begin != get_buffer());
	}

	void reset()
	{
		if( m_capacity )
			base_type::deallocate();

		init();
	}

	void init()
	{
		m_begin = m_end = m_buffer;
		*m_end = T(0);
		m_capacity = m_begin + N;
		m_allocator.set_buffer(m_begin);
	}

	T* get_buffer() const
	{
		return m_buffer;
	}

protected:
	T m_buffer[N];

};



FC_NAMESPACE_END
